package br.urca.controller;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;

import javax.inject.Inject;
import javax.servlet.ServletContext;
import javax.transaction.Transactional;

import br.com.caelum.vraptor.Controller;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.controller.IndexController;
import br.com.caelum.vraptor.jasperreports.Report;
import br.com.caelum.vraptor.jasperreports.download.ReportDownload;
import br.com.caelum.vraptor.jasperreports.formats.ExportFormats;
import br.com.caelum.vraptor.observer.download.Download;
import br.urca.dao.CursoTurnoDAO;
import br.urca.dao.DisciplinasCursadasDAO;
import br.urca.dao.DisciplinasMatriculadasDAO;
import br.urca.dao.DocumentoEmitidoDAO;
import br.urca.dao.HabilitacaoDAO;
import br.urca.http.ProtocoloCursoTurnoHTTP;
import br.urca.interceptor.InterceptResource;
import br.urca.model.AlunoCurso;
import br.urca.model.CursoTurno;
import br.urca.model.DisciplinaCursada;
import br.urca.model.DisciplinaMatriculada;
import br.urca.model.DocumentoEmitido;
import br.urca.model.DocumentoEmitidoPK;
import br.urca.model.Habilitacao;
import br.urca.model.HabilitacaoPK;
import br.urca.model.protocolo.ProtocoloCursoTurno;
import br.urca.model.relatorio.DeclaracaoMatricula;
import br.urca.report.AbstractReport;
import br.urca.session.UsuarioLogado;
import br.urca.util.AutenticacaoDocumento;
import br.urca.util.ETipoDocumento;
import br.urca.util.Paths;

@Controller
@InterceptResource
public class AlunosCursoController {
	
	public static final String SITUACAO_REGULAR = "01";
	public static final String SITUACAO_DISCIPLINA_REGULAR = "AC";

	private Result result;
	private ServletContext context;
	private UsuarioLogado mUsuarioLogado;
	private DocumentoEmitidoDAO mEmitidosDAO;
	private DisciplinasMatriculadasDAO mMatriculadasDAO;
	private DisciplinasCursadasDAO mCursadasDAO;
	private CursoTurnoDAO mCursoTurnoDAO;
	private HabilitacaoDAO mHabilitacaoDAO;
	
	public AlunosCursoController() { }
	
	private AlunoCurso alunoCurso;
	
	@Inject
	public AlunosCursoController(Result result, ServletContext context,
			UsuarioLogado mUsuarioLogado, DocumentoEmitidoDAO mEmitidosDAO,
			DisciplinasMatriculadasDAO mMatriculadasDAO, DisciplinasCursadasDAO mCursadasDAO,
			CursoTurnoDAO mCursoTurnoDAO, HabilitacaoDAO mHabilitacaoDAO) {
		super();
		this.result = result;
		this.context = context;
		this.mUsuarioLogado = mUsuarioLogado;
		this.mEmitidosDAO = mEmitidosDAO;
		this.mMatriculadasDAO = mMatriculadasDAO;
		this.mCursoTurnoDAO = mCursoTurnoDAO;
		this.mHabilitacaoDAO = mHabilitacaoDAO;
		this.mCursadasDAO = mCursadasDAO;
	}
	
	@Get("/declaracao/matricula")
	@Transactional	
	public Download downloadDeclaracaoMatricula() {
		
		try {

			alunoCurso = mUsuarioLogado.getAluno();
			
			if (alunoCurso.getSituacao().getId().equalsIgnoreCase(SITUACAO_REGULAR)) {
	
				List<DisciplinaMatriculada> matriculas = 
						mMatriculadasDAO.buscarPorMatricula(alunoCurso.getMatricula());
				List<DisciplinaCursada> mListCursadas = 
						mCursadasDAO.buscarPorCodOfertaCursando(Paths.PERIODO_PADRAO, alunoCurso.getMatricula());
				
				if ((matriculas != null && !matriculas.isEmpty()) || (mListCursadas != null && !mListCursadas.isEmpty())) {
					
					boolean situacaoRegular = false;
					
					DisciplinaMatriculada matricula = null;
					DisciplinaCursada disciplinaCursada = null;
					
					if (matriculas != null && !matriculas.isEmpty()) {
						for (DisciplinaMatriculada dm: matriculas) {
							if (dm.getSituacao().getCodSituacao()
									.equalsIgnoreCase(SITUACAO_DISCIPLINA_REGULAR)) {
								situacaoRegular = true;
								matricula = dm;
								break;
							}
						}
						
						// Pedido de Júlio para bloquear declaração para alunos novatos...20151 
						if (alunoCurso.getMatricula().substring(0, 5).equalsIgnoreCase("20151")) {
							String mCodCursoTurno = alunoCurso.getCodCursoTurno().trim();
							
							if ((!mCodCursoTurno.equalsIgnoreCase("85X")) && // Letras - Campos Sales
									(!mCodCursoTurno.equalsIgnoreCase("868")) && // Matemática - Campos Sales
									(!mCodCursoTurno.equalsIgnoreCase("876")) && // Ciências Biológicas - Campos Sales
									(!mCodCursoTurno.equalsIgnoreCase("884")) && // Ciências Biológicas - Missão Velha
									(!mCodCursoTurno.equalsIgnoreCase("892")) && // Letras - Missão Velha
									(!mCodCursoTurno.equalsIgnoreCase("825")) && // Direito
									(!mCodCursoTurno.equalsIgnoreCase("817")) && // Ciências Econômicas - Iguatu
									(!mCodCursoTurno.equalsIgnoreCase("833"))) // Enfermagem
								throw new Exception("Declaração não liberada pelo D.E.G.");
							
						}
								
					} 
					if (mListCursadas != null && !mListCursadas.isEmpty()) {
						for (DisciplinaCursada dc: mListCursadas) {
							if (dc.getSituacao().getCodSituacao()
									.equalsIgnoreCase(SITUACAO_DISCIPLINA_REGULAR)) {
								situacaoRegular = true;
								disciplinaCursada = dc;
								break;
							}
						}
					}
					
					//Se passar por essa condição o aluno está regular no curso
					if (situacaoRegular) {
						
						AutenticacaoDocumento mAutenticacao = new AutenticacaoDocumento(
								alunoCurso.getMatricula(),
								ETipoDocumento.DECLARACAO_MATRICULA);						
												
						
						CursoTurno ct = mCursoTurnoDAO.buscarPorCursoTurno(alunoCurso.getCodCursoTurno(),
								alunoCurso.getCurso());
						
						ProtocoloCursoTurno pct = ProtocoloCursoTurnoHTTP
								.getReconhecimentoProtocolo(
										Paths.KEY_APPLICATION,
										alunoCurso.getCodCursoTurno());
						
						DeclaracaoMatricula declaracao = new DeclaracaoMatricula();
						
						declaracao.setAluno(alunoCurso.getAluno().getNome());
						declaracao.setCurso(getCurso(alunoCurso));
						declaracao.setIdentidade(alunoCurso.getAluno().getRg());
						declaracao.setMatricula(alunoCurso.getMatricula());
						declaracao.setSituacao(alunoCurso.getSituacao().getDescricao());
						declaracao.setReconhecimento((pct
								.getReconhecimentoIntegral() != null ? pct
								.getReconhecimentoIntegral() : alunoCurso
								.getCurso().getReconhecimentoMEC())); //alunoCurso.getCurso().getReconhecimentoMEC());
						declaracao.setTurno(getDescricaoTurno(ct));
						if (matricula != null) {
							declaracao.setPeriodo(getPeriodo(matricula));
							declaracao.setAno(getAnoLetivo(matricula));
						} else if (disciplinaCursada != null) {
							declaracao.setPeriodo(getPeriodo(disciplinaCursada));
							declaracao.setAno(getAnoLetivo(disciplinaCursada));
						}
						declaracao.setHabilitacao(getHabilitacaoAluno(new HabilitacaoPK(
										alunoCurso.getCurso().getCodCurso(),
										alunoCurso.getHabilitacao())));
						
						//Criando relatório
						List<DeclaracaoMatricula> list = new ArrayList<DeclaracaoMatricula>();
						list.add(declaracao);
						
				        Report report = new AbstractReport(list, "dec_matricula.jasper", "declaracao_matricula_");
				        String realPath = context.getRealPath("/WEB-INF/reports/images/");
				        report.addParameter("realPath", realPath);
						report.addParameter("compReconhecimento",
								(pct.getReconhecimentoIntegral() != null ? "é reconhecido" : "foi criado"));
				        report.addParameter("md5", mAutenticacao.getAutenticacao());
				        report.addParameter("validade", getValidadeDeclaracao());
				        report.addParameter("validacao", mAutenticacao.getHash());
						
				        if (salvarEmissaoDeDeclaracao(alunoCurso.getMatricula(), mAutenticacao.getHash(), 
				        		(short) ETipoDocumento.DECLARACAO_MATRICULA.getTipo())) {
				        	return new ReportDownload(report, ExportFormats.pdf(), false);
				        } else {
				        	throw new Exception("Falha ao tentar salvar o relatório!");
				        }
					} else {
						msgDeclaracaoNaoEmitida();
					}
					
				} else {
					msgDeclaracaoNaoEmitida();
				}
				
			} else {
				msgDeclaracaoNaoEmitida();
			}
		} catch(Exception e) {
			result.include(
					"mensagem",
					"Desculpe! Ocorreu algum problema e a declaração não pode ser emitida! "+e.getMessage())
					.redirectTo(IndexController.class).index();
		}
		return null;
	}
	
	public void msgDeclaracaoNaoEmitida() {
		result.include(
				"mensagem",
				"Declaração não pode ser emitida! <br />"
						+ "Motivos: Ou sua situação não é regular ou você não tem disciplinas matriculadas com a situação \"ACEITO\".")
				.redirectTo(IndexController.class).index();
	}
	
	public String getDescricaoTurno(CursoTurno ct) {
		String retorno = "NÃO DEFINIDO";
		if (ct != null) {
			switch (ct.getTurno().trim()) {
			case "M":
				retorno = "MANHÃ";
				break;
			case "M/T":
				retorno = "MANHÃ/TARDE";
				break;	
			case "MTN":
				retorno = "MANHÃ/TARDE/NOITE";
				break;		
			case "T":
				retorno = "TARDE";
				break;	
			case "N":
				retorno = "NOITE";
				break;				
			default:
				retorno = "NÃO DEFINIDO";
				break;
			}
		}
		return retorno;	
	}
	
	public String getHabilitacaoAluno(HabilitacaoPK id) {	
		String retorno = "";
		Habilitacao habilitacao = mHabilitacaoDAO.buscarPorId(id);
		if (habilitacao != null && habilitacao.getDescricao() != null) {
			switch (habilitacao.getDescricao().substring(0, 8)) {
			case "BACHAREL":
				retorno = "de BACHARELADO EM ";
				break;
			case "ENGENHEI":
				retorno = "de BACHARELADO EM ";
				break;	
			case "TECNOLOG":
				retorno = "de TECNÓLOGO EM ";
				break;
			case "MESTRADO":
				retorno = "de MESTRADO EM ";
				break;		
			case "FORMAÇÃO":
				retorno = "SEQUENCIAL DE ";
				break;	
			default:
				retorno = "de LICENCIATURA EM ";
				break;
			}
		}
		return retorno;
	}
	
	public String getPeriodo(DisciplinaMatriculada dm) {
		
		String retorno = "";
		if (dm != null) {
			retorno = dm.getId().getCodOferta().substring(4,5);
			retorno += "º";
		}
		
		return retorno;
	}
	
	public String getAnoLetivo(DisciplinaMatriculada dm) {
		
		String retorno = "";
		if (dm != null) {
			retorno = dm.getId().getCodOferta().substring(0,4);
		}
		
		return retorno;
	}
	
	public String getPeriodo(DisciplinaCursada dc) {
		
		String retorno = "";
		if (dc != null) {
			retorno = dc.getId().getCodOferta().substring(4,5);
			retorno += "º";
		}
		
		return retorno;
	}
	
	public String getAnoLetivo(DisciplinaCursada dc) {
		
		String retorno = "";
		if (dc != null) {
			retorno = dc.getId().getCodOferta().substring(0,4);
		}
		
		return retorno;
	}
	
	public String getValidadeDeclaracao() {
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
		Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
		calendar.add(Calendar.DAY_OF_MONTH, 90);
		return "Declaração válida até "+sdf.format(calendar.getTime());
	}
	
	public boolean salvarEmissaoDeDeclaracao(String matricula, String md5, short tipoDocumento) {
		try {
			Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
			DocumentoEmitido doc = new DocumentoEmitido();
	        doc.setId(new DocumentoEmitidoPK(matricula, 
	        		tipoDocumento,
	        		calendar.getTime()));
	        doc.setMd5(md5);
	        calendar.add(Calendar.DAY_OF_MONTH, 90);
	        doc.setValidade(calendar.getTime());
	        
	        mEmitidosDAO.salvar(doc);
	        return true;
		} catch(Exception e) {
			return false;
		}
	}
	
	public String getCurso(AlunoCurso alunoCurso) {
		
		String retorno = "";
		
		if (alunoCurso.getCodCursoTurno().equalsIgnoreCase("086")  && 
				alunoCurso.getHabilitacao().trim().equalsIgnoreCase("01")) {
			retorno = " - EDIFÍCIOS";
		} else if (alunoCurso.getCodCursoTurno().equalsIgnoreCase("086")  && 
				alunoCurso.getHabilitacao().trim().equalsIgnoreCase("02")) {
			retorno = " - TOPOGRAFIA E ESTRADAS";
		} else {
			retorno = alunoCurso.getCurso().getNomeCurso();
		}
		
		return retorno;
	}
	
	/*public String getPeriodo(List<DisciplinaMatriculada> mList) {

		class Periodo {

			public final Comparator<Periodo> POR_CONTADOR = new Comparator<Periodo>() {

				@Override
				public int compare(Periodo o1, Periodo o2) {
					int av = o1.contador, bv = o2.contador;
					return (av == bv) ? 0 : ((av < bv) ? -1 : +1);
				}
			};

			private int contador;
			public String semestre;

			private List<Periodo> mList = new ArrayList<Periodo>();

			public Periodo() {
			}

			public Periodo(String semestre) {
				this.semestre = semestre;
				this.contador = 0;
			}

			public void add(String mString) {
				boolean adicionou = false;
				for (int i = 0; i < mList.size(); i++) {
					if (mList.get(i).semestre.equalsIgnoreCase(mString)) {
						mList.get(i).contador++;
						adicionou = true;
					}
				}
				if (!adicionou) {
					mList.add(new Periodo(mString));
				}
			}

			public String getSemestreAluno() {
				if (mList != null && !mList.isEmpty()) {
					Collections.sort(mList, POR_CONTADOR);
					return mList.get(mList.size() - 1).semestre;
				}
				return "";
			}
		}

		String retorno = "";
		Periodo mPeriodo = new Periodo();

		if (mList != null && !mList.isEmpty()) {
			for (DisciplinaMatriculada dm : mList) {
				retorno = mOfertaDAO.buscarPorOfertaPedido(
						dm.getId().getCodOferta(), dm.getId().getCodPedido())
						.getSemestre();
				if (retorno != null) {
					if (Integer.parseInt(retorno) < 10) {
						retorno = retorno.replace("0", "");
					}
				}
				mPeriodo.add(retorno);
			}
			// retorno = dm.getId().getCodOferta().substring(4,5);
			retorno = mPeriodo.getSemestreAluno();
			retorno += "º";
		}

		return retorno;
	}*/
	
}
